
//#define UTILS_ALL_STANDARD
#define UTILS_ALL_BOOST
//#define UTILS_ALL_BOOST_TR1
#define UTILS_THREAD_BOOST
#define UTILS_SYSTEM_ERROR_BOOST
#define UTILS_TYPE_TRAITS_STANDARD
#define UTILS_CHRONO_BOOST
//
//#define UTILS_UNORDERED_BOOST
//#define UTILS_UNORDERED_BOOST_TR1
//#define UTILS_UNORDERED_STANDARD
#include "unordered_map.h"
#include "smart_ptr.h"
#include "thread.h"
#include "functional.h"
#include "tuple.h"
#include "system_error.h"
#include "type_traits.h"
#include "chrono.h"

#include <iostream>
#include <chrono>

// custom error conditions enum type:
/*
namespace custom_errc { 
enum EC {
  success=0, client_error, server_error, other 
};
}

namespace utils {
template<> struct is_error_condition_enum<custom_errc::EC> : public true_type {};
}

// custom category:
class custom_category_t : public utils::error_category {
public:
  virtual const char* name() const { return "custom"; }
  virtual utils::error_condition default_error_condition (int ev) const {
    if ((ev>=200)&&(ev<300)) return utils::error_condition(custom_errc::success);
    else if ((ev>=400)&&(ev<500)) return utils::error_condition(custom_errc::client_error);
    else if ((ev>=500)&&(ev<600)) return utils::error_condition(custom_errc::server_error);
    else return utils::error_condition(custom_errc::other);
  }
  virtual bool equivalent (const utils::error_code& code, int condition) const {
    return *this==code.category() &&
           static_cast<int>(default_error_condition(code.value()).value())==condition;
  }
  virtual std::string message(int ev) const {
    switch (ev) {
      case 200: return "OK";
      case 403: return "403 Forbidden";
      case 404: return "404 Not Found";
      case 500: return "500 Internal Server Error";
      case 503: return "503 Service Unavailable";
      default: return "Unknown error";
    }
  }
} custom_category;

// make_error_code overload to generate custom conditions:
utils::error_condition make_error_condition (custom_errc e) {
    return utils::error_condition(static_cast<int>(e), custom_category);
}
*/

/*
namespace custom_errc { 
enum EC {
  success=0, 
  client_error,
  server_error,
  other 
};
}

namespace std {
template<> struct is_error_condition_enum<custom_errc::EC> : public true_type {};
}

class custom_category_t : public std::error_category {
 public:
  virtual const char* name() const { return "custom"; }
  virtual std::error_condition default_error_condition (int ev) const {
    if ((ev>=200)&&(ev<300)) return std::error_condition(custom_errc::success);
    else if ((ev>=400)&&(ev<500)) return std::error_condition(custom_errc::client_error);
    else if ((ev>=500)&&(ev<600)) return std::error_condition(custom_errc::server_error);
    else return std::error_condition(custom_errc::other);
  }
  virtual bool equivalent (const std::error_code& code, int condition) const {
    return *this==code.category() &&
        static_cast<int>(default_error_condition(code.value()).value())==condition;
  }
  virtual std::string message(int ev) const {
    switch (ev) {
      case 200: return "OK";
      case 403: return "403 Forbidden";
      case 404: return "404 Not Found";
      case 500: return "500 Internal Server Error";
      case 503: return "503 Service Unavailable";
      default: return "Unknown error";
    }
  }
} custom_category;

std::error_condition make_error_condition (custom_errc::EC e) {
  return std::error_condition(static_cast<int>(e), custom_category);
}
*/

namespace Test {
class TestClass {
  int val_;
 public:
  TestClass(int val) : val_(val) {}

  int val(void) const { return val_; }
};

TestClass operator+(const TestClass& t1, const TestClass& t2) {
  return TestClass(t1.val() + t2.val()); 
}
}

namespace TestRedirect {
  using Test::TestClass;
}

int main(void) {
  utils::unordered_map<int , int, utils::hash<int> > m1;
  utils::shared_ptr<int> int_ptr;
  utils::this_thread::yield();
  utils::function<void (int, int)> f = [](int, int) { return; };
  utils::function<void (int)> f1 = utils::bind(f, 1, utils::placeholders::_1);
  utils::tuple<int, float, double> t1 = utils::make_tuple(123, 123.0f, 123.0);
  utils::error_code ec(errno, utils::generic_category());

  TestRedirect::TestClass tc1(1);
  TestRedirect::TestClass tc2(2);
  TestRedirect::TestClass tc3 = tc1 + tc2;

  return 0;
}

